#include "StdAfx.h"
#include "NetChat.h"


CNetChatServer::CNetChatServer(void)
{
	m_nTimeOut = 500;
}

// class CNetChatClient

CNetChatClient::CNetChatClient(void)
	: m_RecivingWorker(NULL)
{
}

CNetChatClient::~CNetChatClient(void)
{
	Close();
}

bool CNetChatClient::Start(LPCTSTR lpszHostAddress, UINT nHostPort, IListener& rListener, size_t nMaxBufferLen)
{
	bool bRet = false;

	Close();

	m_RecivingWorker = new CRecivingWorker(rListener, nMaxBufferLen);

	if ((NULL != m_RecivingWorker) && m_RecivingWorker->Connect(lpszHostAddress, nHostPort))
	{
		bRet = m_Thread.StartWith(*m_RecivingWorker);
	}

	if (!bRet && (NULL != m_RecivingWorker))
	{
		delete m_RecivingWorker;
		m_RecivingWorker = NULL;
	}

	return bRet;
}

void CNetChatClient::Close()
{
	if (NULL != m_RecivingWorker)
	{
		m_RecivingWorker->End();
		m_RecivingWorker = NULL;
	}

	return;
}

CNetChatClient::CRecivingWorker::CRecivingWorker(IListener& rListener, size_t nMaxBufferLen)
	: m_IsEnd(false)
	, m_IsTerminated(false)
	, m_rListener(rListener)
	, m_nMaxBufferLen(nMaxBufferLen)
	, m_pBuffer(NULL)
{
	m_pBuffer = new BYTE[nMaxBufferLen];
}

CNetChatClient::CRecivingWorker::~CRecivingWorker(void)
{
	m_rListener.OnEnd();

	if (NULL != m_pBuffer)
	{
		delete[] m_pBuffer;
	}
}

bool CNetChatClient::CRecivingWorker::Work()
{
	bool bContinueWorking = true;

	int iRes = m_socketReciver.Receive(m_pBuffer, m_nMaxBufferLen);

	switch (iRes)
	{
	case SOCKET_ERROR :
#ifdef DEBUG
		{
			DWORD dwLastError = GetLastError();
		}
#endif
		break;

	case 0 :
		m_rListener.OnDisconnected();
		bContinueWorking = false; // break
		break;

	default:
		ASSERT(iRes > 0);
		if (iRes > 0)
		{
			m_rListener.OnRecive(m_pBuffer, iRes);
		}
		break;
	}

	return bContinueWorking;
}

bool CNetChatClient::CRecivingWorker::IsEnding()
{
	return m_IsEnd;
}

void CNetChatClient::CRecivingWorker::Terminated()
{
	if (!m_IsTerminated && m_IsEnd)
	{
		delete this;
	}
	else
	{
		m_IsTerminated = true;
	}

	return;
}

bool CNetChatClient::CRecivingWorker::Connect(LPCTSTR lpszHostAddress, UINT nHostPort)
{
	m_socketReciver.Close();
	return (m_socketReciver.Create() &&
		m_socketReciver.Connect(lpszHostAddress, nHostPort));
}

void CNetChatClient::CRecivingWorker::End()
{
	if (m_IsTerminated && !m_IsEnd)
	{
		delete this;
	}
	else
	{
		m_IsEnd = true;
	}

	return;
}
